﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Web;

namespace Uranus.Common
{
    public class RequestCommon
    {
        /// <summary>
        /// 模拟请求
        /// </summary>
        /// <param name="Url">请求地址</param>
        /// <param name="postDataStr">请求参数</param>
        /// <param name="HttpMethods">请求方法</param>
        /// <returns>返回响应字符串</returns>
        public static string SimulationHttp(string Url, string postDataStr, string HttpMethods)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (HttpMethods.ToLower() == "get" ? (postDataStr == "" ? "" : "?") + postDataStr : ""));
            request.Method = HttpMethods;
            if (HttpMethods.ToLower() == "post")
            {
                request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
            }
            else
            {
                request.ContentType = "text/html;charset=UTF-8";

            }
            if (HttpMethods.ToLower() == "post")
            {
                UTF8Encoding encoding = new UTF8Encoding();
                Byte[] bytes = encoding.GetBytes(postDataStr);

                Stream newStream = request.GetRequestStream();
                newStream.Write(bytes, 0, bytes.Length);
                newStream.Close();
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, Encoding.GetEncoding("utf-8"));
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();
            return retString;
        }

        /// <summary>
        /// 模拟请求
        /// </summary>
        /// <param name="Url">请求地址</param>
        /// <param name="postDataStr">请求参数</param>
        /// <param name="HttpMethods">请求方法</param>
        /// <returns>返回响应字符串</returns>
        public static string SimulationHttp(string Url, string postDataStr, string HttpMethods, Encoding encode)
        {
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url + (HttpMethods.ToLower() == "get" ? (postDataStr == "" ? "" : "?") + postDataStr : ""));
            request.Method = HttpMethods;
            if (HttpMethods.ToLower() == "post")
            {
                request.ContentType = "application/x-www-form-urlencoded;charset=UTF-8";
            }
            else
            {
                request.ContentType = "text/html;charset=UTF-8";
            }
            if (encode == Encoding.GetEncoding("gb2312"))
            {
                request.ContentType = "text/html;charset=gb2312";
            }
            if (HttpMethods.ToLower() == "post")
            {
                UTF8Encoding encoding = new UTF8Encoding();
                Byte[] bytes = encoding.GetBytes(postDataStr);

                Stream newStream = request.GetRequestStream();
                newStream.Write(bytes, 0, bytes.Length);
                newStream.Close();
            }
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            StreamReader myStreamReader = new StreamReader(myResponseStream, encode);
            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();
            return retString;
        }

        /// <summary>
        /// 模拟请求(不支持多文件上传)
        /// </summary>
        /// <param name="Url">请求地址</param>
        /// <param name="postDataStr">请求参数</param>
        /// <param name="filebytes">文件流</param>
        /// <param name="HttpMethods">请求方法</param>
        /// <returns>返回响应字符串</returns>
        public static MemoryStream SimulationHttpFile(string Url, Dictionary<string, object> postDataStr, HttpFileCollectionBase files)
        {
            #region
            String BOUNDARY = "----------" + DateTime.Now.Ticks.ToString("x");   // 分隔符 
            StringBuilder parms = new StringBuilder();
            foreach (string key in postDataStr.Keys)
            {
                parms.Append("\r\n--" + BOUNDARY);
                parms.Append("\r\n");
                parms.Append("Content-Disposition: form-data; name=\"" + key + "\"\r\n\r\n");//value前面必须有2个换行  
                parms.Append(postDataStr[key]);//value前面必须有2个换行  
            }
            HttpPostedFileBase file = files[0];
            long filelength = 0; //所有文件总长度
            //string fname;
            byte[] filebytes = null;
            Stream stream = file.InputStream;
            if (stream != null)
            {
                filelength = stream.Length;
                //fname = file.FileName.Substring(0, file.FileName.IndexOf("."));
                parms.Append("\r\n--" + BOUNDARY + "\r\n");
                parms.Append("Content-Disposition: form-data; name=\"" + file.FileName + "\"; filename=\"" + file.FileName + "\"\r\n");
                parms.Append("Content-Type: application/octet-stream");
                parms.Append("\r\n\r\n");
                filebytes = new byte[stream.Length];
                filelength = filelength + filebytes.Length;
                stream.Read(filebytes, 0, filebytes.Length);
                // 设置当前流的位置为流的开始
                stream.Seek(0, SeekOrigin.Begin);
                stream.Close();
            }
            //http请求总长度
            byte[] headbytes = Encoding.UTF8.GetBytes(parms.ToString()); //请求头部
            byte[] end_data = Encoding.UTF8.GetBytes("\r\n--" + BOUNDARY + "\r\n"); //请求结尾

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            request.Method = "post";
            request.ContentType = "multipart/form-data; boundary=" + BOUNDARY;//其他地方的boundary要比这里多--  
            //request.AllowWriteStreamBuffering = false;

            //request.ContentLength = headbytes.Length + filelength + end_data.Length;

            Stream newStream = request.GetRequestStream();
            newStream.Write(headbytes, 0, headbytes.Length);

            //文件
            if (filebytes != null)
            {
                newStream.Write(filebytes, 0, filebytes.Length);
            }

            newStream.Write(end_data, 0, end_data.Length);
            newStream.Close();

            #endregion

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();
            MemoryStream momoryStream = new MemoryStream();
            byte[] bArr = new byte[1024];
            int size = myResponseStream.Read(bArr, 0, (int)bArr.Length);
            while (size > 0)
            {
                momoryStream.Write(bArr, 0, size);
                size = myResponseStream.Read(bArr, 0, (int)bArr.Length);
            }


            //myResponseStream.read
            //StreamReader myStreamReader = new StreamReader(myResponseStream, encode);

            //string retString = myStreamReader.ReadToEnd();
            //myStreamReader.Close();
            //myResponseStream.Close();
            //return retString;
            //momoryStream.Close();
            //   myResponseStream.Close();
            return momoryStream;
        }
        /// <summary>
        /// 模拟请求(不支持多文件上传)
        /// </summary>
        /// <param name="Url">请求地址</param>
        /// <param name="postDataStr">请求参数</param>
        /// <param name="filebytes">文件流</param>
        /// <param name="HttpMethods">请求方法</param>
        /// <returns>返回响应字符串</returns>
        public static string SimulationHttpFile(string Url, Dictionary<string, object> postDataStr, HttpFileCollectionBase files, Encoding encode)
        {
            #region
            String BOUNDARY = "----------" + DateTime.Now.Ticks.ToString("x");   // 分隔符 
            StringBuilder parms = new StringBuilder();
            foreach (string key in postDataStr.Keys)
            {
                parms.Append("\r\n--" + BOUNDARY);
                parms.Append("\r\n");
                parms.Append("Content-Disposition: form-data; name=\"" + key + "\"\r\n\r\n");//value前面必须有2个换行  
                parms.Append(postDataStr[key]);//value前面必须有2个换行  
            }
            HttpPostedFileBase file = files[0];
            long filelength = 0; //所有文件总长度
            //string fname;
            byte[] filebytes = null;
            Stream stream = file.InputStream;
            if (stream != null)
            {
                filelength = stream.Length;
                //fname = file.FileName.Substring(0, file.FileName.IndexOf("."));
                parms.Append("\r\n--" + BOUNDARY + "\r\n");
                parms.Append("Content-Disposition: form-data; name=\"" + file.FileName + "\"; filename=\"" + file.FileName + "\"\r\n");
                parms.Append("Content-Type: application/octet-stream");
                parms.Append("\r\n\r\n");
                filebytes = new byte[stream.Length];
                filelength = filelength + filebytes.Length;
                stream.Read(filebytes, 0, filebytes.Length);
                // 设置当前流的位置为流的开始
                stream.Seek(0, SeekOrigin.Begin);
                stream.Close();
            }
            //http请求总长度
            byte[] headbytes = Encoding.UTF8.GetBytes(parms.ToString()); //请求头部
            byte[] end_data = Encoding.UTF8.GetBytes("\r\n--" + BOUNDARY + "\r\n"); //请求结尾

            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url);
            request.Method = "post";
            request.ContentType = "multipart/form-data; boundary=" + BOUNDARY;//其他地方的boundary要比这里多--  
            //request.AllowWriteStreamBuffering = false;

            //request.ContentLength = headbytes.Length + filelength + end_data.Length;

            Stream newStream = request.GetRequestStream();
            newStream.Write(headbytes, 0, headbytes.Length);

            //文件
            if (filebytes != null)
            {
                newStream.Write(filebytes, 0, filebytes.Length);
            }

            newStream.Write(end_data, 0, end_data.Length);
            newStream.Close();

            #endregion

            HttpWebResponse response = (HttpWebResponse)request.GetResponse();
            Stream myResponseStream = response.GetResponseStream();

            StreamReader myStreamReader = new StreamReader(myResponseStream, encode);

            string retString = myStreamReader.ReadToEnd();
            myStreamReader.Close();
            myResponseStream.Close();
            return retString;
        }

        /// <summary>
        /// 异步模拟请求
        /// </summary>
        /// <param name="url"></param>
        /// <param name="httpMethods">方法</param>
        /// <param name="dictionary">可不传</param>
        /// <returns></returns>
        public static async Task<string> SimulationHttpAsync(string url, string httpMethods, Dictionary<string, string> dictionary=null)
        {
            if (httpMethods.ToLower() == "get" && dictionary != null && dictionary.Count > 0)
            {
                StringBuilder str = new StringBuilder(url);
                if (!url.EndsWith("?"))
                {
                    str.Append("?");
                }
                foreach (KeyValuePair<string, string> keyValuePair in dictionary)
                {
                    str.AppendFormat("{0}={1}&", keyValuePair.Key, keyValuePair.Value);
                }
                url = str.ToString();
            }

            Stream stream = await GetResponseContentAsync(url, dictionary,httpMethods.ToLower());
            if (stream == null) return null;
            return new StreamReader(stream).ReadToEnd();
        }

        private static async Task<Stream> GetResponseContentAsync(string url, Dictionary<string, string> dictionary, string httpMethods)
        {
            var httpClient = new System.Net.Http.HttpClient();
            HttpResponseMessage response = null;
            if (httpMethods == "post")
            {
                httpClient.DefaultRequestHeaders.Add("Method", "Post");
                HttpContent postContent = new FormUrlEncodedContent(dictionary);
                response=await httpClient.PostAsync(url, postContent);
            }
            else
            {
                response = await httpClient.GetAsync(url);
            }
            if (response != null && response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                return await response.Content.ReadAsStreamAsync();
            }
            else
            {
                return null;
            }
        }

    }
}